/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package uns.fit.gis;

/**
 *
 * @author Onno Hommes, Rochester NY, jScience Technologies
 */
// Decompiled by DJ v3.9.9.91 Copyright 2005 Atanas Neshkov  Date: 1/15/2009 2:29:40 PM
// Home Page : http://members.fortunecity.com/neshkov/dj.html  - Check often for new version!
// Decompiler options: packimports(3)


public abstract class MathFP
{

    public MathFP()
    {
    }

    public static int setPrecision(int i)
    {
        if(i > 24 || i < 0)
            return _digits;
        _fbits = i;
        _one = 1L << i;
        _flt = 24 - i;
        _digits = 0;
        _dmul = 1L;
        _fmask = _one - 1L;
        PI = _pi >> (int)_flt;
        E = e[1] >> (int)_flt;
        for(long l = _one; l != 0L;)
        {
            l /= 10L;
            _digits++;
            _dmul *= 10L;
        }

        return _digits;
    }

    public static int getPrecision()
    {
        return _fbits;
    }

    public static long toLong(long l)
    {
        if(l < 0L)
            return -(round(-l, 0) >> _fbits);
        else
            return round(l, 0) >> _fbits;
    }

    public static long toFP(long l)
    {
        return l << _fbits;
    }

    public static long convert(long l, int i)
    {
        long l1 = l >= 0L ? 1L : -1L;
        if(abs(i) < 25L)
            if(_fbits < i)
                l = l + l1 * (1L << (i - _fbits >> 1)) >> i - _fbits;
            else
                l <<= _fbits - i;
        return l;
    }

    public static long toFP(String s)
    {
        int i = 0;
        if(s.charAt(0) == '-')
            i = 1;
        String s1 = "-1";
        int j = s.indexOf('.');
        if(j >= 0)
        {
            for(s1 = s.substring(j + 1, s.length()); s1.length() < _digits; s1 = s1 + "0"){}
            if(s1.length() > _digits)
                s1 = s1.substring(0, _digits);
        } else
        {
            j = s.length();
        }
        long l = 0L;
        if(i != j)
            l = Long.parseLong(s.substring(i, j));
        long l1 = Long.parseLong(s1) + 1L;
        long l2 = (l << _fbits) + (l1 << _fbits) / _dmul;
        if(i == 1)
            l2 = -l2;
        return l2;
    }

    public static String toString(long l)
    {
        boolean flag = false;
        if(l < 0L)
        {
            flag = true;
            l = -l;
        }
        long l1 = l >> _fbits;
        long l2 = _dmul * (l & _fmask) >> _fbits;
        String s;
        for(s = Long.toString(l2); s.length() < _digits; s = "0" + s) {}
        return (flag ? "-" : "") + Long.toString(l1) + "." + s;
    }

    public static String toString(long l, int i)
    {
        if(i > _digits)
            i = _digits;
        String s = toString(round(l, i));
        if (i > 0)
            return s.substring(0, (s.length() - _digits) + i);
        else
            return s.substring(0, (s.length() - _digits) - 1);
    }

    public static long max(long l, long l1)
    {
        return l >= l1 ? l : l1;
    }

    public static long min(long l, long l1)
    {
        return l1 >= l ? l : l1;
    }

    public static long round(long l, int i)
    {
        long l1 = 10L;
        for(int j = 0; j < i; j++)
            l1 *= 10L;

        l1 = div(toFP(5L), toFP(l1));
        if(l < 0L)
            l1 = -l1;
        return l + l1;
    }

    public static long mul(long l, long l1)
    {
        boolean flag = false;
        int i = _fbits;
        long l2 = _fmask;
        if((l & l2) == 0L)
            return (l >> i) * l1;
        if((l1 & l2) == 0L)
            return l * (l1 >> i);
        if(l < 0L && l1 > 0L || l > 0L && l1 < 0L)
            flag = true;
        if(l < 0L)
            l = -l;
        if(l1 < 0L)
            l1 = -l1;
        for(; max(l, l1) >= 1L << 63 - i; i--)
        {
            l >>= 1;
            l1 >>= 1;
            l2 >>= 1;
        }

        long l3 = (l >> i) * (l1 >> i) << i;
        long l4 = (l & l2) * (l1 & l2) >> i;
        l4 += (l & ~l2) * (l1 & l2) >> i;
        l3 = l3 + l4 + ((l & l2) * (l1 & ~l2) >> i) << _fbits - i;
        if(l3 < 0L)
            throw new ArithmeticException("Overflow");
        else
            return flag ? -l3 : l3;
    }

    public static long div(long l, long l1)
    {
        boolean flag = false;
        int i = _fbits;
        if(l1 == _one)
            return l;
        if((l1 & _fmask) == 0L)
            return l / (l1 >> i);
        if(l < 0L && l1 > 0L || l > 0L && l1 < 0L)
            flag = true;
        if(l < 0L)
            l = -l;
        if(l1 < 0L)
            l1 = -l1;
        for(; max(l, l1) >= 1L << 63 - i; i--)
        {
            l >>= 1;
            l1 >>= 1;
        }

        long l2 = (l << i) / l1 << _fbits - i;
        return flag ? -l2 : l2;
    }

    public static long add(long l, long l1)
    {
        return l + l1;
    }

    public static long sub(long l, long l1)
    {
        return l - l1;
    }

    public static long abs(long l)
    {
        if(l < 0L)
            return -l;
        else
            return l;
    }

    public static long sqrt(long l, int i)
    {
        if(l < 0L)
            throw new ArithmeticException("Bad Input");
        if(l == 0L)
            return 0L;
        long l1 = l + _one >> 1;
        for(int j = 0; j < i; j++)
            l1 = l1 + div(l, l1) >> 1;

        if(l1 < 0L)
            throw new ArithmeticException("Overflow");
        else
            return l1;
    }

    public static long sqrt(long l)
    {
        return sqrt(l, 24);
    }

    public static long sin(long l)
    {
        long l1 = mul(l, div(toFP(180L), PI));
        l1 %= toFP(360L);
        if(l1 < 0L)
            l1 = toFP(360L) + l1;
        long l2 = l1;
        if(l1 >= toFP(90L) && l1 < toFP(270L))
            l2 = toFP(180L) - l1;
        else
        if(l1 >= toFP(270L) && l1 < toFP(360L))
            l2 = -(toFP(360L) - l1);
        long l3 = l2 / 90L;
        long l4 = mul(l3, l3);
        long l5 = mul(mul(mul(mul(0xfffffffffffee21aL >> (int)_flt, l4) + (0x14594dL >> (int)_flt), l4) - (0xa55b13L >> (int)_flt), l4) + (long)(0x1921f9c >> (int)_flt), l3);
        return l5;
    }

    public static long asin(long l)
    {
        if(abs(l) > _one)
        {
            throw new ArithmeticException("Bad Input");
        } else
        {
            boolean flag = l < 0L;
            l = abs(l);
            long l1 = mul(mul(mul(mul(0x236cf >> (int)_flt, l) - (long)(0x92748 >> (int)_flt), l) + (long)(0x15acb4 >> (int)_flt), l) - (long)(0x36d0dd >> (int)_flt), l) + (long)(0x1921f27 >> (int)_flt);
            long l2 = PI / 2L - mul(sqrt(_one - l), l1);
            return flag ? -l2 : l2;
        }
    }

    public static long cos(long l)
    {
        return sin(PI / 2L - l);
    }

    public static long acos(long l)
    {
        return PI / 2L - asin(l);
    }

    public static long tan(long l)
    {
        return div(sin(l), cos(l));
    }

    public static long cot(long l)
    {
        return div(cos(l), sin(l));
    }

    public static long atan(long l)
    {
        // return asin(div(l, sqrt(_one + mul(l, l))));
        // Hoan modify
        long _2 = toFP(2);
        long _1 = _one;
        long l2 = mul(l, l);
        if (abs(l) > _1) {
            long _l = sqrt(_1 + l2);
            _l = div(l, _l + _1);
            return mul(_2, atan(_l));
        }
        long mauso = _1;
        long tuso = l;
        long result = 0L;
        for (int i = 0; i < 20; i++) {
            if (i % 2 == 0)
                result = result + div(tuso, mauso);
            else
                result = result - div(tuso, mauso);
            tuso = mul(tuso, l2);
            mauso = mauso + _2;
        }
        return result;
    }

    public static long exp(long l)
    {
        if(l == 0L)
            return _one;
        boolean flag = l < 0L;
        l = abs(l);
        int i = (int)(l >> _fbits);
        long l1 = _one;
        for(int j = 0; j < i / 4; j++)
            l1 = mul(l1, e[4] >> (int)_flt);

        if(i % 4 > 0)
            l1 = mul(l1, e[i % 4] >> (int)_flt);
        l &= _fmask;
        if(l > 0L)
        {
            long l2 = _one;
            long l3 = 0L;
            long l4 = 1L;
            for(int k = 0; k < 16; k++)
            {
                l3 += l2 / l4;
                l2 = mul(l2, l);
                l4 *= k + 1;
                if(l4 > l2 || l2 <= 0L || l4 <= 0L)
                    break;
            }

            l1 = mul(l1, l3);
        }
        if(flag)
            l1 = div(_one, l1);
        return l1;
    }

    public static long log(long l)
    {
        if(l <= 0L)
            throw new ArithmeticException("Bad Input");
        long l1 = 0L;
        int i;
        for(i = 0; l >= _one << 1; i++)
            l >>= 1;

        long l4 = (long)i * (long)(0xb17218 >> (int)_flt);
        long l5 = 0L;
        if(l < _one)
            return -log(div(_one, l));
        l -= _one;
        for(int j = 1; j < 20; j++)
        {
            long l3;
            if(l1 == 0L)
                l3 = l;
            else
                l3 = mul(l1, l);
            if(l3 == 0L)
                break;
            l5 += ((j % 2 != 0 ? 1L : -1L) * l3) / (long)j;
            l1 = l3;
        }

        return l4 + l5;
    }

    public static long pow(long l, long l1)
    {
        boolean flag = l1 < 0L;
        long l2 = _one;
        l1 = abs(l1);
        for(int i = (int)l1 >> _fbits; i-- > 0;)
            l2 = mul(l2, l);

        if(l2 < 0L)
            throw new ArithmeticException("Overflow");
        if(l != 0L)
            l2 = mul(l2, exp(mul(log(l), l1 & _fmask)));
        else
            l2 = 0L;
        if(flag)
            return div(_one, l2);
        else
            return l2;
    }

    public static long atan2(long l, long l1)
    {
        long l2 = 0L;
        if(l1 > 0L)
            l2 = atan(div(l, l1));
        else
        if(l1 < 0L)
        {
            l2 = (l1 >= 0L ? PI : -PI) - atan(abs(div(l, l1)));
        } else
        {
            if(l1 == 0L && l == 0L)
                throw new ArithmeticException("Bad Input");
            l2 = (l >= 0L ? PI : -PI) / 2L;
        }
        return l2;
    }

    private static int _fbits = 24;
    private static int _digits = 8;
    private static long _one;
    private static long _fmask = 0xffffffL;
    private static long _dmul = 0x5f5e100L;
    private static long _flt = 0L;
    private static long _pi;
    private static long e[];
    public static long PI;
    public static long E;
    public static final long MAX_VALUE = 0x7fffffffffffffffL;
    public static final long MIN_VALUE = 0x8000000000000001L;

    static
    {
        _one = 0x1000000L;
        _pi = 0x3243f6aL;
        e = (new long[] {
            _one, 0x2b7e151L, 0x763992eL, 0x1415e5bfL, 0x3699205cL
        });
        PI = _pi;
        E = e[1];
    }
}